package com.whcoding.mybatis.service.impl;

import com.google.common.collect.Lists;
import com.whcoding.mybatis.dao.DeptDao;
import com.whcoding.mybatis.pojo.EquipMessageVO;
import com.whcoding.mybatis.pojo.OrmDeptVO;
import com.whcoding.mybatis.service.DeptService;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Manager
 */
@Service
public class DeptServiceImpl implements DeptService {

	private static final Logger log = LoggerFactory.getLogger(DeptServiceImpl.class);

	@Autowired
	private DeptDao dao;

	/**
	 * 实现批量写入
	 * 需要增加 rewriteBatchedStatements=true在yml文件的jdbc上
	 */
	@Autowired
	SqlSessionFactory sqlSessionFactory;

	/**
	 * 新增数据
	 *
	 * @param deptVO
	 * @return
	 */
	@Override
	public boolean addDept(OrmDeptVO deptVO) {
		return dao.addDept(deptVO);
	}

	/**
	 * 更新数据
	 *
	 * @param deptVO
	 * @return
	 */
	@Override
	public boolean updateDept(OrmDeptVO deptVO) {
		Integer count = dao.updateOrmDept(deptVO);
		return count > 0;
	}

	/**
	 * 删除数据
	 *
	 * @param id 主键ID
	 * @return
	 */
	@Override
	public boolean deleteDeptByID(Long id) {
		Integer count = dao.deleteOrmDeptById(id);
		log.info("数据数据数量为{}",count);
		return count > 0;
	}


	/**
	 * 查询数据-ID
	 *
	 * @param id
	 * @return
	 */
	@Override
	public OrmDeptVO queryDeptById(Long id) {
		return dao.queryDeptById(id);
	}

	private void test(){
		List<EquipMessageVO>  list= dao.findDataTerminalInfoList(1);
		System.out.println(list);
	}

	/**
	 * 查询全部数据
	 *
	 * @return
	 */
	@Override
	public List<OrmDeptVO> queryAllDept() {
		return dao.queryAllDept();
	}


	/**
	 * 查询count
	 *
	 * @return
	 */
	@Override
	public Integer countByDept() {
		return dao.countByDept();
	}

	/**
	 * 事务处理
	 */
	@Transactional(rollbackFor = {RuntimeException.class, Error.class})
	@Override
	public void updateByTransactionalDemo() {
		Long id = 1L;
		OrmDeptVO deptVO = queryDeptById(id);
		int updateNum = dao.updateOrmDept(deptVO);
		log.info("更新数据影响的条数：" + updateNum);
		addDept(deptVO);
		log.info("执行新增数据完成！");
	}


	/**
	 * 批量写入方法一：
	 * 将所有的insert 拼接成一条语句
	 *
	 * @param deptVOS
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void batchInsertOneSql(List<OrmDeptVO> deptVOS) {
		long startTime = System.currentTimeMillis();
		dao.addDeptByOneSQL(deptVOS);
		long endTime = System.currentTimeMillis();
		log.info("合并成一条 SQL 插入耗费时间 {}", (endTime - startTime));
	}

	/**
	 * 批量写入方法二：
	 * 开始sql batch
	 * 效率高
	 *
	 * @param deptVOS
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void batchInsert(List<OrmDeptVO> deptVOS) {
		SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
		try {
			DeptDao deptDao = sqlSession.getMapper(DeptDao.class);
			AtomicInteger atomicInteger = new AtomicInteger();
			System.out.println("batchInsert 插入开始========");
			long start = System.currentTimeMillis();

			for (int i = 0; i <deptVOS.size() ; i++) {
				deptDao.addDept(deptVOS.get(i));
				if (i % 500 == 0 || i == deptVOS.size() - 1) {
					//每1000条数据，手动提交一次，提交后的数据无法回滚
					sqlSession.commit();
					//积累数据量太多容易导致内存溢出，所以每次提交后清理缓存，防止溢出
					sqlSession.clearCache();
					atomicInteger.incrementAndGet();

					//这里可以优化为  sqlSession.flushStatements();
					log.info("当前提交批次为："+atomicInteger.get());

				}
			}
			System.out.println("SqlSession 批量插入耗时："+(System.currentTimeMillis()-start));
		} catch (Exception ex) {
			log.info("批量插入失败："+ex.getMessage());
			//未提交的数据可以回滚
			sqlSession.rollback();
		} finally {
			sqlSession.close();
		}
	}

	@Override
	public void deptTestAll() {
		OrmDeptVO resultVO = dao.queryDeptById(Long.valueOf("1"));
		List<OrmDeptVO> deptVOList = Lists.newArrayList(resultVO);
		dao.insertOrUpdateBatch(deptVOList);
		System.out.println("执行完成");
		Map<String, Object> map = new HashMap<>();
		map.put("deptName", "采购部");
		map.put("deptNo", "CG_001");

		List<String> deptNoList = new ArrayList<>();
		deptNoList.add("CG_001");
		deptNoList.add("KF_001");
		deptNoList.add("CP_001");
		Integer count = dao.countByDeptByDeptName(map);
		List<String> deptNameList = dao.listDeptName(map);
		List<Map<String, Object>> mapList = dao.findDeptNameAndDeptNo(deptNoList);
		//TODO
		if (null != mapList && mapList.size() > 0) {
			Map<String, List<Integer>> paramGroupMap = mapList.stream()
					.collect(Collectors.groupingBy(paramMap -> map.get("deptCode").toString(),
							Collectors.mapping(paramMap -> (Integer) map.get("deptName"), Collectors.toList())));

			for (Map.Entry<String, List<Integer>> entry : paramGroupMap.entrySet()) {
				{
					log.info("paramGroupMap分组后的数据为：key={},value={}", entry.getKey(), entry.getValue());
				}
			}
		}
	}

	@Override
	public Integer findMaxDeptId(Integer deptType) {
		return dao.findMaxDeptId(deptType);
	}
}
